/* ***** BEGIN LICENSE BLOCK *****
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except
 * in compliance with the License.You may obtain a copy of the License at
 *  http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the License.
 *
 * The Original Code is jresearch.org code.
 *
 * The Initial Developer of the Original Code is
 * Dmitry Belov <bel@jresearch.org>
 *
 * Contributor(s): .
 * * ***** END LICENSE BLOCK ***** */
package com.jred.jforum.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;


/**
 * DOCUMENT ME!
 *
 * @author dbelov
 */
public class DesEncrypter {
    Cipher ecipher;
    Cipher dcipher;

    // 8-byte Salt
    byte[] salt = {
        (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
        (byte) 0x35, (byte) 0xE3, (byte) 0x03
    };

    // Iteration count
    int iterationCount = 19;

    /**
     * Creates a new DesEncrypter object.
     *
     * @param passPhrase DOCUMENT ME!
     *
     * @throws InvalidKeySpecException DOCUMENT ME!
     * @throws NoSuchAlgorithmException DOCUMENT ME!
     * @throws NoSuchPaddingException DOCUMENT ME!
     * @throws InvalidKeyException DOCUMENT ME!
     * @throws InvalidAlgorithmParameterException DOCUMENT ME!
     */
    public DesEncrypter(String passPhrase)
        throws InvalidKeySpecException, NoSuchAlgorithmException, 
            NoSuchPaddingException, InvalidKeyException, 
            InvalidAlgorithmParameterException {
        // Create the key
        KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt,
                iterationCount);
        SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
                                        .generateSecret(keySpec);
        ecipher = Cipher.getInstance(key.getAlgorithm());
        dcipher = Cipher.getInstance(key.getAlgorithm());

        // Prepare the parameter to the ciphers
        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt,
                iterationCount);

        // Create the ciphers
        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
    }

    private DesEncrypter() {
    }

    /**
     * DOCUMENT ME!
     *
     * @param str DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws UnsupportedEncodingException DOCUMENT ME!
     * @throws IllegalStateException DOCUMENT ME!
     * @throws IllegalBlockSizeException DOCUMENT ME!
     * @throws BadPaddingException DOCUMENT ME!
     */
    public String encrypt(String str)
        throws UnsupportedEncodingException, IllegalStateException, 
            IllegalBlockSizeException, BadPaddingException {
        // Encode the string into bytes using UTF-8
        byte[] utf8 = str.getBytes("UTF-8");

        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);

        // Encode bytes to base64 to get a string
        return new sun.misc.BASE64Encoder().encode(enc);
    }

    /**
     * DOCUMENT ME!
     *
     * @param str DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     * @throws IllegalStateException DOCUMENT ME!
     * @throws IllegalBlockSizeException DOCUMENT ME!
     * @throws BadPaddingException DOCUMENT ME!
     */
    public String decrypt(String str)
        throws IOException, IllegalStateException, IllegalBlockSizeException, 
            BadPaddingException {
        // Decode base64 to get bytes
        byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);

        // Decrypt
        byte[] utf8 = dcipher.doFinal(dec);

        // Decode using UTF-8
        return new String(utf8, "UTF8");
    }
}
